<?php

namespace common\modules\user;

use common\modules\user\map\UserMap;
use xing\helper\exception\ApiCodeException;
use xing\helper\exception\ModelYiiException;
use Yii;
use yii\web\IdentityInterface;

/**
 * This is the model class for table "user".
 *
 * @property int $userId 用户id，主键自增
 * @property string|null $mobile 手机号
 * @property int|null $recommendUserId 推荐人
 * @property string|null $thirdId 第三方身份标识，如微信openid
 * @property string|null $loginToken 登陆TOKEN
 * @property int|null $status 用户状态:10正常 0软删除
 * @property float $sqc sqc
 * @property float $calculation 算力
 * @property int $authorLevel 作者等级
 * @property int $experience 经验
 * @property string $nickname 昵称
 * @property int|null $lastLoginTime 上次登陆时间
 * @property int|null $loginNumber 登陆次数
 * @property string|null $lang 用户语言
 * @property string|null $lastLoginIp 上次登陆ip
 * @property string|null $deviceToken 设备码
 * @property int|null $createTime 注册时间
 * @property string|null $mobileVendor 手机厂商
 * @property string|null $mobileModel 手机型号
 * @property string|null $auth_key
 * @property string|null $regSources 注册来源
 * @property string|null $password_reset_token
 * @property string|null $password_hash
 * @property string|null $registerIP 注册ip
 * @property int|null $unreadMessage 未读消息
 * @property int|null $withdrawLock 提现锁定
 * @property string|null $say 说说
 * @property string $bkog 职业
 * @property int $cityId 城市
 * @property int $isAuthenticate 是否个人认证
 */
class User extends \xing\helper\yii\BaseActiveModel implements IdentityInterface
{

    const STATUS_DELETED = 0;
    const STATUS_ACTIVE = 10;
    const STATUS_WAIT_REGISTER = 2;

    public static $status = [
        self::STATUS_ACTIVE => '正常',
        self::STATUS_DELETED => '禁用',
//        self::STATUS_WAIT_REGISTER => '等待完善资料',
    ];

    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'user';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['status', 'recommendUserId', 'loginNumber', 'createTime', 'unreadMessage', 'withdrawLock', 'sex', 'cityId', 'authorLevel', 'experience', 'isAuthenticate'], 'integer'],
            [['calculation', 'sqc'], 'number'],
            [['mobile'], 'string', 'max' => 15],
            [['thirdId'], 'string', 'max' => 32],
            [['loginToken', 'lastLoginIp', 'deviceToken', 'auth_key', 'password_reset_token', 'password_hash', 'registerIP'], 'string', 'max' => 64],
            [['lang', 'regSources'], 'string', 'max' => 20],
            [['mobileVendor', 'mobileModel'], 'string', 'max' => 50],
            [['say'], 'string', 'max' => 500],
            [['avatar'], 'string', 'max' => 200],
            [['bkog'], 'string', 'max' => 30],
            [['mobile', 'nickname', 'thirdId'], 'unique'],
            [['lastLoginTime'], 'safe'],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'userId' => '用户id',
            'mobile' => '手机号',
            'recommendUserId' => '推荐人',
            'thirdId' => 'openid',
            'loginToken' => '登陆TOKEN',
            'status' => '用户状态',
            'sqc' => 'sqc',
            'calculation' => '算力',
            'authorLevel' => '作者等级',
            'experience' => '等级',
            'nickname' => '昵称',
            'lastLoginTime' => '上次登陆时间',
            'loginNumber' => '登陆次数',
            'lang' => '用户语言',
            'lastLoginIp' => '上次登陆ip',
            'deviceToken' => '设备码',
            'createTime' => '注册时间',
            'mobileVendor' => '手机厂商',
            'mobileModel' => '手机型号',
            'auth_key' => 'Auth Key',
            'regSources' => '注册来源',
            'password_reset_token' => 'Password Reset Token',
            'password_hash' => 'Password Hash',
            'registerIP' => '注册ip',
            'unreadMessage' => '未读消息',
            'withdrawLock' => '提现锁定',
            'say' => '说说',
            'isAuthenticate' => '是否个人认证'
        ];
    }




    public function scenarios()
    {
        $scenarios = parent::scenarios();
        $scenarios['user'] = ['thirdId', 'wxUnionId', 'regSources', ];
        $scenarios['admin'] = ['thirdId', 'wxUnionId', 'regSources', 'mobile', 'authorLevel', 'status'];
        return $scenarios;
    }

// 明确列出每个字段，适用于你希望数据表或模型属性
//修改时不导致你的字段修改（保持后端API兼容性）
    public function fields()
    {
        $fields = parent::fields();
        // 删除一些包含敏感信息的字段
        unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);

        return $fields;
    }

    public function extraFields()
    {
        return [];
    }


    /**
     * @inheritdoc
     */
    public static function findIdentity($id)
    {
        return static::findOne(['userId' => $id, 'status' => self::STATUS_ACTIVE]);
    }

    /**
     * @inheritdoc
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['api_token' => $token, 'status' => self::STATUS_ACTIVE]);
    }

    /**
     * Finds user by password reset token
     *
     * @param string $token password reset token
     * @return static|null
     */
    public static function findByPasswordResetToken($token)
    {
        if (!static::isPasswordResetTokenValid($token)) {
            return null;
        }

        return static::findOne([
            'password_reset_token' => $token,
            'status' => self::STATUS_ACTIVE,
        ]);
    }

    /**
     * Finds out if password reset token is valid
     *
     * @param string $token password reset token
     * @return bool
     */
    public static function isPasswordResetTokenValid($token)
    {
        if (empty($token)) {
            return false;
        }

        $timestamp = (int)substr($token, strrpos($token, '_') + 1);
        $expire = Yii::$app->params['user.passwordResetTokenExpire'];
        return $timestamp + $expire >= time();
    }

    /**
     * @inheritdoc
     */
    public function getId()
    {
        return $this->getPrimaryKey();
    }

    /**
     * @inheritdoc
     */
    public function getAuthKey()
    {
        return $this->auth_key;
    }

    /**
     * @inheritdoc
     */
    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }

    /**
     * Validates password
     *
     * @param string $password password to validate
     * @return bool if password provided is valid for current user
     */
    public function validatePassword($password)
    {
        return Yii::$app->security->validatePassword($password, $this->password_hash);
    }

    /**
     * Generates password hash from password and sets it to the model
     *
     * @param string $password
     */
    public function setPassword($password)
    {
        $this->password_hash = Yii::$app->security->generatePasswordHash($password);
    }

    /**
     * Generates "remember me" authentication key
     */
    public function generateAuthKey()
    {
        $this->auth_key = Yii::$app->security->generateRandomString();
    }

    /**
     * Generates new password reset token
     */
    public function generatePasswordResetToken()
    {
        $this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
    }

    /**
     * Removes password reset token
     */
    public function removePasswordResetToken()
    {
        $this->password_reset_token = null;
    }
    /**
     * 删除会员缓存
     * @param $userId
     * @throws \Exception
     */
    public static function deleteUserCache($userId)
    {
        $m = self::findOne($userId);
        !empty($m) && $m->delCache();
    }

    /**
     * 根据手机读取用户信息
     * @param $mobile
     * @return array|null|User
     */
    public static function getMobileToUser($mobile)
    {
        return self::find()->where(['mobile' => $mobile])->one();
    }

    /**
     * @param $mobile
     * @return bool
     */
    public static function existsMobile($mobile)
    {
        return self::find()->where(['mobile' => $mobile])->exists();
    }

    /**
     * 获取用户名
     * @param $userId
     * @return mixed|null
     */
    public static function getUserName($userId)
    {
        if (empty($userId)) return null;
        $data = static::readInfo($userId);
        return !empty($data) ? $data['username'] : null;
    }

    /**
     * 获取会员id
     * @param $username
     * @return mixed|null
     */
    public static function readUserId($username)
    {
        if (empty($username)) return null;
        $data = self::find()->where(['username' => $username])->one();
        return !empty($data) ? $data['userId'] : null;
    }

    /**
     * @param $userId
     * @param $token
     * @param string $loginDriveToken
     * @param string $loginMobileModel
     * @param string $loginMobileVendor
     * @return static|null|\yii\db\ActiveRecord
     * @throws ModelYiiException
     * @throws \Exception
     */
    public static function updateLogin($userId, $token, $loginDriveToken = '', $loginMobileModel = '', $loginMobileVendor = '')
    {
        if (empty($userId)) return null;
        $m = self::readInfo($userId);
        if (empty($m)) throw new \Exception('没有这个用户');

        $m->loginToken = $token;
        $m->lastLoginTime = date('Y-m-d H:i:s');
        $m->loginNumber ++;
        $m->lastLoginIp = Yii::$app->request->userIP;
        $m->deviceToken = $loginDriveToken;
        $loginMobileModel && $m->mobileModel = $loginMobileModel;
        $loginMobileVendor && $m->mobileVendor = $loginMobileVendor;
        return $m->logicSave();
    }

    /**
     * 读取token
     * @param $mobile
     * @return mixed|null
     */
    public static function getToken($mobile)
    {
        if (empty($mobile)) return null;
        $m = self::find()->where(['mobile' => $mobile])->one();
        return !empty($m) ? $m->loginToken : null;
    }

    /**
     * 根据token读取用户
     * @return array|null|bool|\yii\db\ActiveRecord
     */
    public static function getTokenToUser()
    {
        $post = file_get_contents("php://input");
        if (is_string($post)) $post = json_decode($post, 1);

        $userId = ($post['loginUserId'] ?? null)
            ?: Yii::$app->request->post('loginUserId')
                ?: Yii::$app->request->get('loginUserId');

        $token = ($post['loginToken'] ?? null)
            ?: Yii::$app->request->post('loginToken')
                ?: Yii::$app->request->get('loginToken');

        if (empty($token)) return null;

        $userInfo = self::findOne($userId);
        if (empty($userInfo) || $userInfo->loginToken !== $token) return false;
        return $userInfo;
    }


    /**
     * 接口数据格式化
     * @param User $member
     * @return array|User
     */
    public static function apiFormat(User $member)
    {
        $member = $member->toArray();
        return $member;
    }

    /**
     * 更新会员最后登陆时间
     * @param $userId
     * @return array|User|null
     * @throws ModelYiiException
     */
    public static function updateLoginTime($userId)
    {
        $user = self::readInfo($userId);
        $cacheKey = 'U:ULT:' . $userId;
        if (!empty($user) && empty(Yii::$app->cache->get($cacheKey))) {
            $user->lastLoginTime = date('Y-m-d H:i:s');
            if (!$user->save()) throw new ModelYiiException($user);
            Yii::$app->cache->set($cacheKey, 1, 300);
        }
        return $user;
    }

    /**
     * 读取用户设备码
     * @param $userId
     * @return string
     */
    public static function readDriveToken($userId)
    {
        $user = self::readInfo($userId);
        return $user->loginDriveToken ?? '';
    }

    /**
     * 用户退出
     * @param $userId
     * @throws ApiCodeException
     * @throws ModelYiiException
     */
    public static function logout($userId)
    {
        $m = self::readInfo($userId);
        if (empty($m)) throw new ApiCodeException(ResponseMap::ERROR_DATA_EMPTY, '用户');

        $m->deviceToken = '';
        $m->loginToken = '';
        return $m->logicSave();

    }

    /**
     * 读取没有缓存的用户数据
     * @param $userId
     * @return static|$this|\yii\db\ActiveRecord|null
     */
    public static function readNoCacheMember($userId)
    {
        return self::find()->where(['userId' => $userId])->one();
    }

    /**
     * 读取用户手机
     * @param $userId
     * @return mixed|string
     */
    public static function readMobile($userId)
    {
        return self::readFieldValue('mobile', $userId);
    }

    /**
     * 创建用户
     * @param $mobile
     * @param string $password
     * @param null $recommendUserId
     * @param string $regSources
     * @param string $lang
     * @return User
     * @throws ModelYiiException
     */
    public static function create($mobile, $password = '', $recommendUserId = null, $regSources = 'app', $lang = 'zh-CN')
    {

        $user = new User();
        $user->mobile = $mobile;
        $user->setPassword($password);
        $user->generateAuthKey();

        $user->recommendUserId = $recommendUserId;
        $user->createTime = time();
        $user->registerIP = Yii::$app->request->getUserIP();
        $user->regSources = $regSources;
        $user->status = User::STATUS_ACTIVE;
        $user->lang = $lang ?: '';
        if (!$user->save()) throw new ModelYiiException($user);
        return $user;
    }
    /**
     * 清空未读消息数
     * @param $userId
     * @return mixed
     * @throws ModelYiiException
     */
    public static function clearUnreadMessage($userId)
    {
        $m = self::findOne($userId);
        $m->unreadMessage = 0;
        return $m->logicSave();
    }

    /**
     * 第三方登陆
     * @param $thirdId
     * @return null|\yii\db\ActiveRecord|static
     */
    public static function thirdByInfo($thirdId)
    {
        return self::findOne(['thirdId' => $thirdId]);
    }

    public static function readInfo($userId)
    {
        return self::findOne($userId);
    }
    public static function readBaseInfo($userId, $select = [])
    {
        $select = array_merge(UserMap::$baseField, $select);
        return self::find()->where(['userId' => $userId])->select($select)->one();
    }
}
